<template>
  <div style="width: 100%; height: 100%">
    <div ref="earthContainer" style="width: 100%; height: 100%"></div>
    <div style="position: absolute; left: 18px; top: 18px">
      <button @click="showBar">柱状图</button>
      <button @click="showCamera">监控</button>
      <button @click="showHeatMap">热力图</button>
    </div>
  </div>
</template>

<script>
// 1 创建Earth的vue组件
var EarthComp = {
  data() {
    return {
      message: "页面加载于 " + new Date().toLocaleString(),
      _earth: undefined, // 注意：Earth和Cesium的相关变量放在vue中，必须使用下划线作为前缀！
      _bgImagery: undefined,
      cameraShow: false,
      heatMapShow: false,
      barShow: false,
      initChildrenLength: 0,
    };
  },
  methods: {
    createEarth() {
      // 1.1.1 创建地球
      var earth = new XE.Earth(this.$refs.earthContainer);
      earth.interaction.picking.enabled = true;


      earth.weather.atmosphere.enabled = false;
      const bloom = earth.postProcess.bloom;
      bloom.enabled = true;
      bloom.glowOnly = false;
      bloom.contrast = 119;
      bloom.brightness = -0.4;
      bloom.delta = 0.9;
      bloom.sigma = 3.78;
      bloom.stepSize = 5;
      bloom.isSelected = false;


      // 1.1.2 添加默认地球影像

      earth.sceneTree.root = require('@/assets/json/sc.json')

      var viewer = earth.czm.viewer;
      viewer.scene.hdrEnabled = true; //hdr
      viewer.scene.globe.baseColor = Cesium.Color.BLACK;
      viewer.scene.sun.show = false; //太阳光
      viewer.scene.moon.show = false;//月亮光
      viewer.scene.skyBox.show = false;//
      viewer.scene.globe.enableLighting = false; //全局光
      viewer.scene.globe.globeAlpha = 0.001;
      viewer.scene.fxaa = true; //图像改善
      viewer.scene.skyAtmosphere.show = false; //天空


      this.initChildrenLength = earth.sceneTree.root.children.length;
      this._handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);


      this._grayTileset = new Cesium.Cesium3DTileset({
        //url: 'http://localhost:9000/model/98d5b2a0db8011ea8888597ed93d5b4b/tileset.json',
        url: 'http://129.204.173.206:8089/sh_3dtiles/tileset.json',
        show: false
      })
      this._grayTileset.style = new Cesium.Cesium3DTileStyle({
        color: "vec4(0.7, 0.7, 0.7,0.1)"
      })
      viewer.scene.primitives.add(this._grayTileset);

      this._earth = earth;
      this._h = undefined

      this.addODLine()
      this.setBuildingClickHandler(true)


      earth.camera.flyAround([2.1206125026580582, 0.545178729438238, 15], 3000, [0, -Math.PI / 5, 0], 0, 3.14 / 50);

      // 仅为调试方便用
      // window.earth = earth;
      // window.heatmap = h;


    },
    getObjClassName(obj) {
      var str = obj.constructor + '';
      var res = ''
      var start = str.replace("function", "|").indexOf('|');
      if (start !== -1) {
        var end = str.replace("function", "|").indexOf("(");
        if (end !== -1) {
          res = str.replace("function", "|").slice(start + 2, end)
        }
      }
      return res
    },


    setBuildingClickHandler(bool) {
      this._handler.setInputAction((click) => {
        if(bool) {
          this._earth.sceneTree.root.children.length = this.initChildrenLength
          var pickedFeature = this._earth.czm.viewer.scene.pick(click.position);
          if (typeof pickedFeature !== 'undefined' && (this.getObjClassName(pickedFeature) === 'Cesium3DTileFeature')) {
            // console.log(pickedFeature.getPropertyNames())
            var clickPosition = this._earth.pickPosition(click.position)
            var name = pickedFeature.getProperty('NAME')
            var height = pickedFeature.getProperty('HEIGHT')
            var json = {
              "czmObject": {
                "xbsjType": "Pin",
                "xbsjGuid": "c2ab17db-36b2-4982-add6-cece932b9b68",
                "name": "城科",
                "evalString": "const width = 200;\nconst height = 100;\nfunction createLabelCanvas(p) {\n  if (p._labelDiv) {\n    p._earth.czm.viewer.container.removeChild(p._labelDiv);\n    p._labelDiv = undefined;\n  }\n  const labelDiv = document.createElement('div');\n  labelDiv.style = 'width:'+width+'px;height: '+height+'px;position: absolute; pointer-events: none;'\n\n  p._earth.czm.viewer.container.appendChild(labelDiv);\n  p._labelDiv = labelDiv;\n\n  var dis = XE.MVVM.watch(() => {\n    labelDiv.style.display = p.enabled ? 'block' : 'none';\n  });\n\n  p.disposers.push(() => {\n    if (p._labelDiv) {\n      p._earth.czm.viewer.container.removeChild(p._labelDiv);\n      p._labelDiv = undefined;\n    }\n    dis();\n  });\n\n  const labelCanvas = document.createElement('canvas');\n  labelCanvas.style = 'width: 100%;height: 100%;';\n\n  labelCanvas.width = width;\n  labelCanvas.height = height;\n  labelDiv.appendChild(labelCanvas);\n  return labelCanvas;\n}\n\nfunction createDrawFunc(p) {\n  const labelCanvas = createLabelCanvas(p);\n  const ctx = labelCanvas.getContext('2d');\n\n  function draw(w) {\n    ctx.clearRect(0, 0, width, height);\n\n    ctx.save();\n    ctx.lineWidth = 2;\n    ctx.strokeStyle = 'rgb(31, 255,255)';\n    ctx.beginPath();\n    ctx.moveTo(width, height);\n    ctx.lineTo(width-height, 22);\n    ctx.lineTo(0, 22);\n    ctx.stroke();\n    ctx.restore();\n    ctx.font = \"16px console\"; \n    ctx.fillStyle = 'rgb(255, 255, 0)';\n    ctx.fillText('" +
                    name + " " + height + "米', 0, 20);\n    ctx.restore();\n  }\n\n  p._dDraw = draw;\n}\n\ncreateDrawFunc(p);\n\nlet d = 0;\nlet c = 0;\np._dDraw(c);\nconst preUpdateListener = p._earth.czm.scene.preUpdate.addEventListener(() => {\n  if (d !== c) {\n    c += (d - c) * 0.1;\n    if (Math.abs(c - d) < 0.1) {\n      c = d;\n    }\n    p._dDraw(c);\n  }\n});\np.disposers.push(() => preUpdateListener && preUpdateListener());\n\nconst container = p._earth.czm.viewer.container;\nconst unwatch = XE.MVVM.watch(() => [...p.winPos], winPos => {\n  if (p._labelDiv) {\n    p._labelDiv.style.left = (winPos[0] -  p._labelDiv.clientWidth) + 'px';\n    p._labelDiv.style.bottom = winPos[3]+'px';\n  } \n});\np.disposers.push(() => {\n  unwatch && unwatch();\n});",
                "position": clickPosition,
                "isDivImage": true,
                "origin": [
                  1.390625,
                  -0.7
                ],
                "pinBuilder": {},
                "far": 1073741824
              }
            }
            this._earth.sceneTree.root.children.push(json);
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },

    switchBuildingMode(num) {
      switch (num) {
        case 0:
          this._earth.sceneTree.$refs.tileset.czmObject.enabled = true
          this._grayTileset.show = false
          this.setBuildingClickHandler(true)
          break
        case 1:
          this._earth.sceneTree.$refs.tileset.czmObject.enabled = false
          this._grayTileset.show = true
          this.setBuildingClickHandler(false)
          break
        default:
          break
      }

    },

    showBar() {
      this.barShow = !this.barShow
      this._earth.czm.viewer.entities.getById('bar').show = this.barShow
      if (this.barShow) {
        this.switchBuildingMode(1)
      } else {
        this.switchBuildingMode(0)
      }
    },
    showCamera() {
      this.cameraShow = !this.cameraShow
      this._earth.sceneTree.$refs.camera.enabled = this.cameraShow
      if (this.cameraShow) {
        this.switchBuildingMode(1)
        this._earth.sceneTree.$refs.camera.children.map(
            item => {
              // item.czmObject.show = this.cameraShow
              item.czmObject.onclick = () => {
                alert(item.czmObject.pinBuilder.extText)
              }
            }
        )
      } else {
        this.switchBuildingMode(0)
        // this._earth.sceneTree.$refs.camera.children.map(
        //     item => {
        //       item.czmObject.show = this.cameraShow
        //     }
        // )
      }
    },

    addODLine() {
      var barData = require('@/assets/json/bar.json')

      var barEntity = new Cesium.Entity({
        id: 'bar',
        show: false
      });
      this._earth.czm.viewer.entities.add(barEntity)

      for (var i = 0; i < barData.length; i++) {
        var color = Cesium.Color.fromHsl(0.1 - barData[i].value * 0.1 / 1500, 1.0, 1 - barData[i].value / 1500);
        //
        var surfacePosition = Cesium.Cartesian3.fromDegrees(
            barData[i].x,
            barData[i].y,
            0
        );
        var heightPosition = Cesium.Cartesian3.fromDegrees(
            barData[i].x,
            barData[i].y,
            barData[i].value
        );

        //WebGL Globe only contains lines, so that's the only graphics we create.
        var polyline = new Cesium.PolylineGraphics();
        polyline.material = new Cesium.ColorMaterialProperty(color);
        polyline.width = new Cesium.ConstantProperty(3);
        polyline.arcType = new Cesium.ConstantProperty(
            Cesium.ArcType.NONE
        );
        polyline.positions = new Cesium.ConstantProperty([
          surfacePosition,
          heightPosition,
        ]);

        //The polyline instance itself needs to be on an entity.
        var entity = new Cesium.Entity({
          show: true,
          polyline: polyline,
          parent: barEntity
        });
        this._earth.czm.viewer.entities.add(entity)
      }


      this._odlines = new XE.Obj.ODLines(this._earth);
      this._odlines.translucentPass = false;
      //this._odlines.color = [1, 1, 1, 1];

      this.loadODLineData((data, timeDuration) => {
        this._odlines.data = data;
        this._odlines.timeDuration = timeDuration;
        this._odlines.playing = true;
      });

    },

    loadODLineData(dataFunc) {
      Cesium.Resource.fetchJson('./assets/json/line.json').then((data) => {

        var timeDuration = 5.0;
        var moveBaseDuration = 1.0;

        var hStep = 300 / (data.length - 1);

        var type = null;
        var oldType = null;
        var ptList = []
        var busLines = [];
        data.map((item) => {
              type = item.oid
              if (type === oldType) {
                ptList.push([item.x * Math.PI / 180.0, item.y * Math.PI / 180.0])
              } else {
                if (oldType !== null) {
                  busLines.push({
                    positions: ptList,
                    color: [Math.random() * 0.5 + 0.5, Math.random() * 0.8 + 0.2, 0.0, 1.0],
                    width: 3.0,
                    startTime: timeDuration * Math.random(),
                    duration: moveBaseDuration + 1.0 * Math.random()
                  });
                }
                ptList = []
                ptList.push([item.x * Math.PI / 180.0, item.y * Math.PI / 180.0])
              }
              oldType = type
            }
        )
        dataFunc(busLines, timeDuration);
      });
    },

    showHeatMap() {
      this.heatMapShow = !this.heatMapShow
      if (this.heatMapShow) {
        this.switchBuildingMode(1)
        var heatconfig = {
          position: [121.499934 * Math.PI / 180.0, 31.238495 * Math.PI / 180.0, 0],
          width: 10000,
          height: 10000,
          gradient: [
            [0, "rgba(0, 255, 0, 0.1)"],
            [0.2, "rgba(0, 0, 255, 0.1)"],
            [0.6, "rgba(255, 255, 0, 0.1)"],
            [1, "red"]
          ],
          maxValue: 1000,
          dataWidth: 400,
          dataHeight: 400
        }
        this._h = new XE.Obj.HeatMap(this._earth);
        this._h.xbsjFromJSON(heatconfig);

        const h337Instance = h337.create({
          container: document.createElement('div'),
          //maxOpacity: 0.5,
          radius: 100,
          blur: 0.9,
          width: 400, // 必须设置宽高，否则h337的创建会有问题
          height: 400,
          backgroundColor: 'rgba(0, 0, 58, 0.96)'
        });
        const resultHeatMapData = [{x: 166, y: 320, value: 2.1885915085560192, radius: 25},
          {x: 244, y: 296, value: 9.699812949104427, radius: 9},
          {x: 33, y: 116, value: 2.1566944215352657, radius: 33}]
        var heatMin = 0;
        var heatMax = 10;
        h337Instance.setData({
          min: heatMin,
          max: heatMax,
          data: resultHeatMapData,
        });
        // copyfromOtherCanvas函数可以直接拷贝别的canvas中的内容，前提是需要保证canvas尺寸一致！
        this._h.copyfromOtherCanvas(h337Instance._renderer.canvas);
      } else {
        this._h = this._h && this._h.destroy();
        this.switchBuildingMode(0)
      }

    },

    createCesium() {
      window.viewer = new Cesium.Viewer(this.$refs.earthContainer);
    }
  },
  // 1.1 资源创建
  mounted() {
    XE.ready().then(() => {
      // 加载标绘插件
      const p1 = XE.HTML.loadJS('./js/earthsdk/XbsjEarth-Plugins/plottingSymbol.js');
      const p2 = XE.HTML.loadJS('./js/earthsdk/XbsjEarth-Plugins/customPrimitive.js');
      const p3 = XE.HTML.loadJS('./js/earthsdk/XbsjEarth-Plugins/customPrimitiveImage.js');
      const p5 = XE.HTML.loadJS('./js/earthsdk/XbsjEarth-Plugins/plottingSymbol2.js');
      const p4 = XE.HTML.loadJS('./js/earthsdk/XbsjEarth-Plugins/three.min.js');
      const p6 = XE.HTML.loadJS('./js/earthsdk/XbsjEarth-Plugins/heatmap.js');
      return Promise.all([p1, p2, p3, p4, p5, p6]);
    }).then(() => {
      if (typeof XE !== 'undefined') {
        this.createEarth();
      } else if (typeof Cesium !== 'undefined') {
        this.createCesium();
      }
    });

  },

  // 1.2 资源销毁
  beforeDestroy() {
    // vue程序销毁时，需要清理相关资源
    this._earth = this._earth && this._earth.destroy();
  }
};

export default EarthComp;
</script>
